//+------------------------------------------------------------------+
//|                                                   T_SupportSR.mq5 |
//|                  Converted from T-language logic (user provided)  |
//|  Plots short/mid/long pressure & support levels with forward set  |
//|  and shows basic top/bottom divergence arrows.                    |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_plots 8

// Pressure lines
#property indicator_label1  "短期压力"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrWhite
#property indicator_style1  STYLE_SOLID
#property indicator_width1  3

#property indicator_label2  "中期压力"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrCyan
#property indicator_style2  STYLE_SOLID
#property indicator_width2  3

#property indicator_label3  "长期压力"
#property indicator_type3   DRAW_HISTOGRAM
#property indicator_color3  clrRed
#property indicator_style3  STYLE_SOLID
#property indicator_width3  3

// Support lines
#property indicator_label4  "短期支撑"
#property indicator_type4   DRAW_HISTOGRAM
#property indicator_color4  clrFuchsia
#property indicator_style4  STYLE_SOLID
#property indicator_width4  3

#property indicator_label5  "中期支撑"
#property indicator_type5   DRAW_HISTOGRAM
#property indicator_color5  clrYellow
#property indicator_style5  STYLE_SOLID
#property indicator_width5  3

#property indicator_label6  "长期支撑"
#property indicator_type6   DRAW_HISTOGRAM
#property indicator_color6  clrLime
#property indicator_style6  STYLE_SOLID
#property indicator_width6  3

// Divergence arrows (bottom/top)
#property indicator_label7  "底背离▲"
#property indicator_type7   DRAW_ARROW
#property indicator_color7  clrMagenta
#property indicator_style7  STYLE_SOLID
#property indicator_width7  1

#property indicator_label8  "顶背离▼"
#property indicator_type8   DRAW_ARROW
#property indicator_color8  clrRed
#property indicator_style8  STYLE_SOLID
#property indicator_width8  1

//--- input parameters (none for now)

//--- buffers
double g_shortPressure[];
double g_midPressure[];
double g_longPressure[];

double g_shortSupport[];
double g_midSupport[];
double g_longSupport[];

double g_bottomDiv[];
double g_topDiv[];

//--- internal state for forward windows
int    sp_active_index   = -1; // 短期压力 信号触发索引
int    sp_expire_index   = -1;
double sp_active_value   = 0.0;

int    mp_active_index   = -1; // 中期压力
int    mp_expire_index   = -1;
double mp_active_value   = 0.0;

int    lp_active_index   = -1; // 长期压力
int    lp_expire_index   = -1;
double lp_active_value   = 0.0;

int    ss_active_index   = -1; // 短期支撑
int    ss_expire_index   = -1;
double ss_active_value   = 0.0;

int    ms_active_index   = -1; // 中期支撑
int    ms_expire_index   = -1;
double ms_active_value   = 0.0;

int    ls_active_index   = -1; // 长期支撑
int    ls_expire_index   = -1;
double ls_active_value   = 0.0;

//---
int OnInit()
{
    SetIndexBuffer(0, g_shortPressure, INDICATOR_DATA);
    SetIndexBuffer(1, g_midPressure,   INDICATOR_DATA);
    SetIndexBuffer(2, g_longPressure,  INDICATOR_DATA);

    SetIndexBuffer(3, g_shortSupport,  INDICATOR_DATA);
    SetIndexBuffer(4, g_midSupport,    INDICATOR_DATA);
    SetIndexBuffer(5, g_longSupport,   INDICATOR_DATA);

    SetIndexBuffer(6, g_bottomDiv,     INDICATOR_DATA);
    SetIndexBuffer(7, g_topDiv,        INDICATOR_DATA);

    PlotIndexSetInteger(6, PLOT_ARROW, 233); // ▲
    PlotIndexSetInteger(7, PLOT_ARROW, 234); // ▼

    ArraySetAsSeries(g_shortPressure, true);
    ArraySetAsSeries(g_midPressure,   true);
    ArraySetAsSeries(g_longPressure,  true);
    ArraySetAsSeries(g_shortSupport,  true);
    ArraySetAsSeries(g_midSupport,    true);
    ArraySetAsSeries(g_longSupport,   true);
    ArraySetAsSeries(g_bottomDiv,     true);
    ArraySetAsSeries(g_topDiv,        true);

    return(INIT_SUCCEEDED);
}

//--- helpers
static int HighestShift(const double &prices[], const int start_shift, const int length)
{
    int best_shift = start_shift;
    double best_val = prices[start_shift];
    int last = start_shift + length - 1;
    for(int s = start_shift; s <= last; ++s)
    {
        if(prices[s] > best_val)
        {
            best_val = prices[s];
            best_shift = s;
        }
    }
    return best_shift;
}

static int LowestShift(const double &prices[], const int start_shift, const int length)
{
    int best_shift = start_shift;
    double best_val = prices[start_shift];
    int last = start_shift + length - 1;
    for(int s = start_shift; s <= last; ++s)
    {
        if(prices[s] < best_val)
        {
            best_val = prices[s];
            best_shift = s;
        }
    }
    return best_shift;
}

static double RollingHighest(const double &prices[], const int shift, const int length)
{
    double v = prices[shift];
    int last = shift + length - 1;
    for(int s = shift; s <= last; ++s) if(prices[s] > v) v = prices[s];
    return v;
}

static double RollingLowest(const double &prices[], const int shift, const int length)
{
    double v = prices[shift];
    int last = shift + length - 1;
    for(int s = shift; s <= last; ++s) if(prices[s] < v) v = prices[s];
    return v;
}

// simple EMA computed left-to-right in time (from past to present)
static void ComputeEMA(const double &src[], double &dst[], const int rates_total, const int period)
{
    if(period <= 1)
    {
        for(int i = rates_total-1; i >= 0; --i) dst[i] = src[i];
        return;
    }
    const double k = 2.0 / (period + 1.0);
    // initialize with the oldest bar
    double prev = src[rates_total-1];
    dst[rates_total-1] = prev;
    for(int i = rates_total-2; i >= 0; --i)
    {
        double ema = (src[i] - prev) * k + prev;
        dst[i] = ema;
        prev = ema;
    }
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
{
    if(rates_total < 120) // need enough history for 61-window and divergence calcs
        return 0;

    ArraySetAsSeries(High, true);
    ArraySetAsSeries(Low,  true);
    ArraySetAsSeries(Close,true);

    // clear output for newly added bars
    int start = (prev_calculated==0 ? rates_total-1 : rates_total - prev_calculated);
    if(start < 0) start = rates_total-1;
    for(int i = 0; i <= start; ++i)
    {
        int s = i; // shift index
        if(s >= rates_total) break;
        g_shortPressure[s] = EMPTY_VALUE;
        g_midPressure[s]   = EMPTY_VALUE;
        g_longPressure[s]  = EMPTY_VALUE;
        g_shortSupport[s]  = EMPTY_VALUE;
        g_midSupport[s]    = EMPTY_VALUE;
        g_longSupport[s]   = EMPTY_VALUE;
        g_bottomDiv[s]     = EMPTY_VALUE;
        g_topDiv[s]        = EMPTY_VALUE;
    }

    // recompute all to maintain forward windows consistently
    sp_active_index = mp_active_index = lp_active_index = -1;
    ss_active_index = ms_active_index = ls_active_index = -1;
    sp_expire_index = mp_expire_index = lp_expire_index = -1;
    ss_expire_index = ms_expire_index = ls_expire_index = -1;

    // divergence prep arrays
    static double risk_src[];
    static double risk_ema[];
    ArrayResize(risk_src, rates_total);
    ArrayResize(risk_ema, rates_total);
    ArraySetAsSeries(risk_src, true);
    ArraySetAsSeries(risk_ema, true);

    // main loop from oldest to newest (descending shifts)
    for(int i = rates_total-1; i >= 0; --i)
    {
        // --- Pressure conditions ---
        // a: highest(high,6)==high && high>refBefore(high,1)
        bool a_short = false;
        if(i+5 < rates_total && i+1 < rates_total)
        {
            int h6 = HighestShift(High, i, 6);
            a_short = (h6 == i && High[i] > High[i+1]);
        }
        if(a_short)
        {
            sp_active_index = i;
            sp_expire_index = i - 5;
            sp_active_value = High[i];
        }
        if(sp_active_index != -1 && i >= sp_expire_index)
            g_shortPressure[i] = sp_active_value;

        // b: highest(high,21)==high && high>refBefore(high,1)
        bool a_mid = false;
        if(i+20 < rates_total && i+1 < rates_total)
        {
            int h21 = HighestShift(High, i, 21);
            a_mid = (h21 == i && High[i] > High[i+1]);
        }
        if(a_mid)
        {
            mp_active_index = i;
            mp_expire_index = i - 20;
            mp_active_value = High[i];
        }
        if(mp_active_index != -1 && i >= mp_expire_index)
            g_midPressure[i] = mp_active_value;

        // c: highest(high,61)==high && high>refBefore(high,1)
        bool a_long = false;
        if(i+60 < rates_total && i+1 < rates_total)
        {
            int h61 = HighestShift(High, i, 61);
            a_long = (h61 == i && High[i] > High[i+1]);
        }
        if(a_long)
        {
            lp_active_index = i;
            lp_expire_index = i - 60;
            lp_active_value = High[i];
        }
        if(lp_active_index != -1 && i >= lp_expire_index)
            g_longPressure[i] = lp_active_value;

        // --- Support conditions ---
        bool s_short = false;
        if(i+5 < rates_total && i+1 < rates_total)
        {
            int l6 = LowestShift(Low, i, 6);
            s_short = (l6 == i && Low[i] < Low[i+1]);
        }
        if(s_short)
        {
            ss_active_index = i;
            ss_expire_index = i - 5;
            ss_active_value = Low[i];
        }
        if(ss_active_index != -1 && i >= ss_expire_index)
            g_shortSupport[i] = ss_active_value;

        bool s_mid = false;
        if(i+20 < rates_total && i+1 < rates_total)
        {
            int l21 = LowestShift(Low, i, 21);
            s_mid = (l21 == i && Low[i] < Low[i+1]);
        }
        if(s_mid)
        {
            ms_active_index = i;
            ms_expire_index = i - 20;
            ms_active_value = Low[i];
        }
        if(ms_active_index != -1 && i >= ms_expire_index)
            g_midSupport[i] = ms_active_value;

        bool s_long = false;
        if(i+60 < rates_total && i+1 < rates_total)
        {
            int l61 = LowestShift(Low, i, 61);
            s_long = (l61 == i && Low[i] < Low[i+1]);
        }
        if(s_long)
        {
            ls_active_index = i;
            ls_expire_index = i - 60;
            ls_active_value = Low[i];
        }
        if(ls_active_index != -1 && i >= ls_expire_index)
            g_longSupport[i] = ls_active_value;

        // --- Divergence risk source (compute later EMA) ---
        // hdy = ema( 100*(close - LL34)/(HH34-LL34) , 4 )
        if(i+33 < rates_total)
        {
            double ll34 = RollingLowest(Low, i, 34);
            double hh34 = RollingHighest(High, i, 34);
            double denom = (hh34 - ll34);
            double val = 0.0;
            if(denom > 0.0)
                val = 100.0 * (Close[i] - ll34) / denom;
            risk_src[i] = val;
        }
        else
        {
            risk_src[i] = 50.0;
        }
    }

    // compute EMA(4) of risk_src into risk_ema
    ComputeEMA(risk_src, risk_ema, rates_total, 4);

    // place divergence arrows
    for(int i = rates_total-2; i >= 0; --i)
    {
        g_bottomDiv[i] = EMPTY_VALUE;
        g_topDiv[i]    = EMPTY_VALUE;
        // 底背离: close<ref(close,1) && 风险值>ref(风险值,1) && 风险值<15
        if(Close[i] < Close[i+1] && risk_ema[i] > risk_ema[i+1] && risk_ema[i] < 15.0)
        {
            g_bottomDiv[i] = Low[i] * 0.999; // a bit below low
        }
        // 顶背离: close>ref(close,1) && 风险值<ref(风险值,1) && 风险值>85
        if(Close[i] > Close[i+1] && risk_ema[i] < risk_ema[i+1] && risk_ema[i] > 85.0)
        {
            g_topDiv[i] = High[i] * 1.001; // a bit above high
        }
    }

    return(rates_total);
}

//+------------------------------------------------------------------+

